package com.sojson.service.impl.thread;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.sojson.config.exception.TransException;
import com.sojson.constant.ConstantMessageSystemTemplate;
import com.sojson.constant.Lock;
import com.sojson.dao.PostApplyDao;
import com.sojson.entity.po.BalanceLog;
import com.sojson.entity.po.Member;
import com.sojson.entity.po.Post;
import com.sojson.entity.po.Salary;
import com.sojson.entity.vo.PostApplyVo;
import com.sojson.entity.vo.SalaryVo;
import com.sojson.enums.EBalanceCount;
import com.sojson.enums.EBalanceTotalType;
import com.sojson.enums.EBalanceType;
import com.sojson.enums.EMessageSystemType;
import com.sojson.enums.ESalaryStatus;
import com.sojson.enums.core.ERoleType;
import com.sojson.service.BalanceLogService;
import com.sojson.service.MemberService;
import com.sojson.service.MessageSystemService;
import com.sojson.service.PostService;
import com.sojson.service.SalaryService;
import com.sojson.util.DateUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.id.GUIDUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 工资Service线程实现类
 * 
 * @author liu
 * @date 2021-05-23
 */
@Slf4j
@Component
public class SalaryThreadImpl {

    @Lazy
    @Autowired
    private SalaryThreadImpl salaryThreadImpl;
    @Autowired
    private SalaryService salaryService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private PostService postService;
    @Autowired
    private BalanceLogService balanceLogService;
    @Autowired
    private MessageSystemService messageSystemService;
    @Resource
    private PostApplyDao postApplyDaoImpl;

    /**
     * 导入工资
     * @param file 
     */
    @Async
    public void importSalary(List<Salary> importExcel) {
        int code = ESalaryStatus.CREATE_NO.getCode();
        String userNoMsg = "此手机号的用户不存在";
        String postNoMsg = "职位不存在";
        for (Salary salary : importExcel) {
            try {
                Salary s = new Salary();
                s.setPostId(salary.getPostId());
                s.setMobile(salary.getMobile());
                s.setIssueDate(salary.getIssueDate());
                synchronized (Lock.ADD_SALARY) {
                    int countByDto = salaryService.countByDto(s);
                    if (countByDto > 0) {
                        continue;
                    }

                    Set<String> hashSet = new HashSet<>();
                    hashSet.add(ERoleType.USER.getKey());
                    Member findByMobile = memberService.findByRoleMobile(hashSet, salary.getMobile());
                    if (StringUtil.isBlankObject(findByMobile)) {
                        salary.setStatus(code);
                        salary.setMsg(userNoMsg);
                        salaryService.insert(salary);
                        continue;
                    }
                    salary.setUserId(findByMobile.getId());
                    Post findById = postService.findById(salary.getPostId());
                    if (StringUtil.isBlankObject(findById)) {
                        salary.setStatus(code);
                        salary.setMsg(postNoMsg);
                        salaryService.insert(salary);
                        continue;
                    }

                    salaryService.insert(salary);
                }
            } catch (Exception e) {
                StringBuilder stringBuilder = new StringBuilder("薪资导入失败: {");
                stringBuilder.append("职位ID").append(":").append(salary.getPostId()).append(",");
                stringBuilder.append("用户手机号").append(":").append(salary.getMobile()).append(",");
                stringBuilder.append("发放日期").append(":")
                    .append(DateUtil.dateToString(salary.getIssueDate(), DateUtil.YYYY_MM_DD)).append(",");
                stringBuilder.append("},").append(e.getMessage());
                log.error(stringBuilder.toString());
            }
        }
    }

    /**
     * 重新导入工资
     * 
     * @param id
     * @return
     */
    public int reImportSalary(Integer id) {
        int updateById = 0;
        Salary salary = salaryService.findById(id);

        synchronized (Lock.ADD_SALARY) {
            Salary s = new Salary();
            s.setPostId(salary.getPostId());
            s.setMobile(salary.getMobile());
            s.setIssueDate(salary.getIssueDate());
            s.setStatus(ESalaryStatus.CREATE_YES.getCode());
            int countByDto = salaryService.countByDto(s);
            if (countByDto > 0) {
                throw new TransException("用户此岗位此日期的工资已存在！");
            }

            if (StringUtil.isBlankObject(salary.getUserId())) {
                Set<String> hashSet = new HashSet<>();
                hashSet.add(ERoleType.USER.getKey());
                Member findByMobile = memberService.findByRoleMobile(hashSet, salary.getMobile());
                if (StringUtil.isBlankObject(findByMobile)) {
                    throw new TransException("此手机号的用户不存在！");
                }
                salary.setUserId(findByMobile.getId());
            }
            Post findById = postService.findById(salary.getPostId());
            if (StringUtil.isBlankObject(findById)) {
                throw new TransException("职位不存在！");
            }

            salary.setStatus(ESalaryStatus.CREATE_YES.getCode());
            salary.setMsg("");
            updateById = salaryService.updateById(salary);
            if (updateById < 1) {
                throw new TransException("修改失败，请重试！");
            }
        }
        return updateById;
    }

    /**
     * 发放工资
     * 
     * @return
     */
    @Async
    public void send() {
        Salary s = new Salary();
        s.setStatus(ESalaryStatus.AFFIRM.getCode());
        String generateGuid = GUIDUtil.generateGuid();
        List<SalaryVo> listByDto = salaryService.sendList(s);
        for (SalaryVo salary : listByDto) {
            try {
                salary.setIssueNo(generateGuid);
                String date = DateUtil.dateToString(salary.getIssueDate(), DateUtil.YYYY_MM_DD);
                synchronized (Lock.BALANCE_LOG) {
                    salaryThreadImpl.sendGo(salary, date);
                }
            } catch (Exception e) {
                e.printStackTrace();
                StringBuilder stringBuilder = new StringBuilder("薪资发放失败: {");
                stringBuilder.append("职位ID").append(":").append(salary.getPostId()).append(",");
                stringBuilder.append("用户手机号").append(":").append(salary.getMobile()).append(",");
                stringBuilder.append("发放日期").append(":")
                    .append(DateUtil.dateToString(salary.getIssueDate(), DateUtil.YYYY_MM_DD)).append(",");
                stringBuilder.append("},").append(e.getMessage());
                log.error(stringBuilder.toString());
            }
        }
    }

    /**
     * 发放工资
     * 
     * @param date 发放日期
     * @return
     * @throws Exception 
     */
    @Transactional
    public int sendGo(SalaryVo salary, String date) throws Exception {
        // 修改工资信息
        Salary s = new Salary();
        s.updateInit();
        s.setId(salary.getId());
        s.setStatus(ESalaryStatus.SEND_YES.getCode());
        s.setIssueNo(salary.getIssueNo());
        int updateSalary = salaryService.updateById(s);
        if (updateSalary < 1) {
            throw new TransException("修改工资状态失败！");
        }

        BigDecimal total = salary.getTotal();
        Integer userId = salary.getUserId();
        Member findById = memberService.findById(userId);
        if (StringUtil.isBlankObject(findById)) {
            throw new TransException("用户不存在！");
        }
        BigDecimal brokerage = findById.getBrokerage();

        // 修改佣金
        Member member = new Member();
        member.updateInit();
        member.setId(userId);
        member.setBrokerage(total.add(brokerage));
        member.setBrokerageSum(total.add(findById.getBrokerageSum()));
        int updateById = memberService.updatePartialById(member);
        if (updateById < 1) {
            throw new TransException("修改用户佣金失败！");
        }

        // 添加佣金记录
        String orderNo = salary.getOrderNo();
        StringBuilder mark = new StringBuilder(orderNo).append("-");
        String postName = salary.getPostName();
        if (StringUtil.isNotBlankObject(postName)) {
            mark.append(postName).append("-");
        }
        mark.append(date);
        BalanceLog balanceLog = new BalanceLog();
        balanceLog.insertInit("兼职到账", userId, total, brokerage, EBalanceType.POST.getCode(), null,
            EBalanceTotalType.BALANCE.getCode(), EBalanceCount.ADD.getCode(), orderNo, mark.toString());
        int insert = balanceLogService.insert(balanceLog);
        if (insert < 1) {
            throw new TransException("添加佣金记录！");
        }

        // 发送消息
        messageSystemService.send(ConstantMessageSystemTemplate.getBrokerageAccount(total, s.getUpdatedAt()),
            EMessageSystemType.BALANCE.getCode(), EBalanceTotalType.BALANCE.getCode(), balanceLog.getId() + "",
            findById);

        PostApplyVo pa = new PostApplyVo();
        pa.setPostId(salary.getPostId());
        pa.setUserId(userId);
        postApplyDaoImpl.setStatusToSuccess(pa);
        return updateById;
    }

}